#include "common.h"
#include <inttypes.h>
#include <iostream>
// core status
enum {
    STATE_RUNNING,
    STATE_GOODTRAP,
    STATE_BADTRAP,
    STATE_ABORT
};

static int g_trapCode = STATE_RUNNING;
static uint64_t g_trapPC = 0;
static uint64_t g_cycleCnt = 0, g_instrCnt = 0;

bool is_finish() {
    return g_trapCode != STATE_RUNNING;
}
void set_abort(){
    g_trapCode = STATE_ABORT;
}
void haltCheck(uint64_t pc, uint64_t inst, uint64_t a0){
    extern bool instcheck(uint64_t pc, uint64_t inst);
    if(!instcheck(pc, inst)){
        printf("pc=%lx, inst=%lx\n", pc, inst);
        printf(FONT_COLOR_RED"monitor.cpp: Instruction Check Fail!\n"COLOR_NONE);
        set_abort();
        return;
    }
    if(inst == HALT){
        if(a0 == 0)
            g_trapCode = STATE_GOODTRAP;
        else
            g_trapCode = STATE_BADTRAP;
    }
}

extern "C" void monitor(uint64_t trapPC, uint64_t cycleCnt, uint64_t instrCnt){
    g_trapPC = trapPC;
    g_cycleCnt = cycleCnt;
    g_instrCnt = instrCnt;
}





int display_trapinfo(uint64_t max_cycles) {
  switch (g_trapCode) {
    case STATE_GOODTRAP:
      eprintf(ANSI_COLOR_GREEN "HIT GOOD TRAP at pc = 0x%" PRIx64 "\n" ANSI_COLOR_RESET, g_trapPC);
      break;
    case STATE_BADTRAP:
      eprintf(ANSI_COLOR_RED "HIT BAD TRAP at pc = 0x%" PRIx64 "\n" ANSI_COLOR_RESET, g_trapPC);
      break;
    case STATE_ABORT:
      eprintf(ANSI_COLOR_RED "ABORT at pc = 0x%" PRIx64 "\n" ANSI_COLOR_RESET, g_trapPC);
      break;
    case STATE_RUNNING:
      eprintf(ANSI_COLOR_RED "Timeout after %" PRIx64 " cycles\n" ANSI_COLOR_RESET, max_cycles);
      break;
     default:
       eprintf(ANSI_COLOR_RED "Failed! trapCode = %d " PRIx64 "\n" ANSI_COLOR_RESET, g_trapCode);
  }

  double ipc = (double)g_instrCnt / g_cycleCnt;
  eprintf(ANSI_COLOR_MAGENTA "total guest instructions = %" PRIu64 "\n" ANSI_COLOR_RESET, g_instrCnt);
  eprintf(ANSI_COLOR_MAGENTA "instrCnt = %" PRIu64 ", cycleCnt = %" PRIu64 ", IPC = %lf\n" ANSI_COLOR_RESET,
      g_instrCnt, g_cycleCnt, ipc);
  return g_trapCode != STATE_GOODTRAP;

}